from fastapi import APIRouter, HTTPException, Query, Path
from typing import List, Optional, Literal
from pydantic import BaseModel, Field
from app.model.model_lesson import Lesson, LessonCreate, LessonUpdate, LessonResponse, LessonWithLearnsResponse

router = APIRouter(prefix="/lesson", tags=["Lesson"])

class LearnAssociationRequest(BaseModel):
    learn_id: int = Field(..., description="要关联的学习课程ID")

class PaginatedLessonResponse(BaseModel):
    """分页课程响应模型"""
    data: List[LessonResponse] = Field(..., description="课程列表")
    total: int = Field(..., description="总数量")
    page_num: int = Field(..., description="当前页码")
    page_size: int = Field(..., description="每页数量")
    total_pages: int = Field(..., description="总页数")

@router.post("/", response_model=LessonResponse, summary="创建课程")
async def create_lesson(lesson_data: LessonCreate):
    """
    创建新的课程
    """
    try:
        lesson = Lesson(
            lessonId=lesson_data.lessonId,
            source=lesson_data.source,
            process=lesson_data.process,
            factory=lesson_data.factory,
            projectName=lesson_data.projectName,
            occurenceTime=lesson_data.occurenceTime,
            problemType=lesson_data.problemType,
            faReport=lesson_data.faReport,
            problemDescription=lesson_data.problemDescription,
            improvement=lesson_data.improvement,
            creator=lesson_data.creator,
            updater=lesson_data.updater
        )
        lesson_id = lesson.save()
        
        # 重新获取完整数据
        created_lesson = Lesson.get_by_id(lesson_id)
        return created_lesson.to_dict()
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"创建课程失败: {str(e)}")

@router.get("/", response_model=PaginatedLessonResponse, summary="获取所有课程")
async def get_all_lessons(
    page_num: int = Query(1, ge=1, description="页码，从1开始"),
    page_size: int = Query(20, ge=1, le=100, description="每页数量，默认20"),
    search: Optional[str] = Query(None, description="按LessonID搜索"),
    factory: Optional[str] = Query(None, description="按工厂筛选")
):
    """
    获取所有课程，支持分页、搜索和筛选
    """
    try:
        # 计算偏移量
        offset = (page_num - 1) * page_size
        
        # 获取数据
        if search:
            lessons = Lesson.search_by_lesson_id(search)
            total = len(lessons)
            # 手动分页
            lessons = lessons[offset:offset + page_size]
        elif factory:
            lessons = Lesson.get_by_factory(factory)
            total = len(lessons)
            # 手动分页
            lessons = lessons[offset:offset + page_size]
        else:
            # 获取总数
            total = Lesson.get_count()
            # 获取分页数据
            lessons = Lesson.get_all(page_size, offset)
        
        # 计算总页数
        total_pages = (total + page_size - 1) // page_size
        
        return PaginatedLessonResponse(
            data=[lesson.to_dict() for lesson in lessons],
            total=total,
            page_num=page_num,
            page_size=page_size,
            total_pages=total_pages
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取课程失败: {str(e)}")

@router.get("/{lesson_id}", response_model=LessonWithLearnsResponse, summary="获取单个课程")
async def get_lesson_by_id(lesson_id: str = Path(..., description="课程ID或LessonID")):
    """
    根据ID或LessonID获取单个课程及其关联的学习课程
    支持整数ID（如：1）或LessonID字符串（如：Lesson-20251010-v1）
    """
    try:
        # 尝试判断是整数ID还是LessonID字符串
        if lesson_id.isdigit():
            # 整数ID
            lesson = Lesson.get_by_id(int(lesson_id))
        else:
            # LessonID字符串
            lesson = Lesson.get_by_lesson_id(lesson_id)
        
        if not lesson:
            raise HTTPException(status_code=404, detail="课程不存在")
        
        result = lesson.to_dict()
        result['learns'] = lesson.get_learns()
        return result
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取课程失败: {str(e)}")

@router.put("/{lesson_id}", response_model=LessonResponse, summary="更新课程")
async def update_lesson(
    lesson_id: str = Path(..., description="课程ID或LessonID"),
    lesson_data: LessonUpdate = None
):
    """
    更新课程信息
    支持整数ID（如：1）或LessonID字符串（如：Lesson-20251010-v1）
    """
    try:
        # 尝试判断是整数ID还是LessonID字符串
        if lesson_id.isdigit():
            # 整数ID
            lesson = Lesson.get_by_id(int(lesson_id))
        else:
            # LessonID字符串
            lesson = Lesson.get_by_lesson_id(lesson_id)
        
        if not lesson:
            raise HTTPException(status_code=404, detail="课程不存在")
        
        # 更新字段
        if lesson_data.lessonId is not None:
            lesson.lessonId = lesson_data.lessonId
        if lesson_data.source is not None:
            lesson.source = lesson_data.source
        if lesson_data.process is not None:
            lesson.process = lesson_data.process
        if lesson_data.factory is not None:
            lesson.factory = lesson_data.factory
        if lesson_data.projectName is not None:
            lesson.projectName = lesson_data.projectName
        if lesson_data.occurenceTime is not None:
            lesson.occurenceTime = lesson_data.occurenceTime
        if lesson_data.problemType is not None:
            lesson.problemType = lesson_data.problemType
        if lesson_data.faReport is not None:
            lesson.faReport = lesson_data.faReport
        if lesson_data.problemDescription is not None:
            lesson.problemDescription = lesson_data.problemDescription
        if lesson_data.improvement is not None:
            lesson.improvement = lesson_data.improvement
        if lesson_data.updater is not None:
            lesson.updater = lesson_data.updater
        
        lesson.save()
        return lesson.to_dict()
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"更新课程失败: {str(e)}")

@router.delete("/{lesson_id}", summary="删除课程")
async def delete_lesson(lesson_id: str = Path(..., description="课程ID或LessonID")):
    """
    删除课程及其所有关联关系
    支持整数ID（如：1）或LessonID字符串（如：Lesson-20251010-v1）
    """
    try:
        # 尝试判断是整数ID还是LessonID字符串
        if lesson_id.isdigit():
            # 整数ID
            lesson = Lesson.get_by_id(int(lesson_id))
        else:
            # LessonID字符串
            lesson = Lesson.get_by_lesson_id(lesson_id)
        
        if not lesson:
            raise HTTPException(status_code=404, detail="课程不存在")
        
        success = lesson.delete()
        if success:
            return {"message": "课程删除成功"}
        else:
            raise HTTPException(status_code=500, detail="删除课程失败")
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"删除课程失败: {str(e)}")

@router.post("/{lesson_id}/learns", summary="为课程添加学习课程")
async def add_learn_to_lesson(
    lesson_id: str = Path(..., description="课程ID或LessonID"),
    learn_data: LearnAssociationRequest = None
):
    """
    为课程添加关联的学习课程
    支持整数ID（如：1）或LessonID字符串（如：Lesson-20251010-v1）
    """
    try:
        # 尝试判断是整数ID还是LessonID字符串
        if lesson_id.isdigit():
            # 整数ID
            lesson = Lesson.get_by_id(int(lesson_id))
        else:
            # LessonID字符串
            lesson = Lesson.get_by_lesson_id(lesson_id)
        
        if not lesson:
            raise HTTPException(status_code=404, detail="课程不存在")
        
        # 检查学习课程是否存在
        from app.model.model_learn import Learn
        learn = Learn.get_by_id(learn_data.learn_id)
        if not learn:
            raise HTTPException(status_code=404, detail="学习课程不存在")
        
        success = lesson.add_to_learn(learn_data.learn_id)
        if success:
            return {"message": "学习课程关联成功"}
        else:
            return {"message": "学习课程已关联或关联失败"}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"添加学习课程关联失败: {str(e)}")

@router.delete("/{lesson_id}/learns/{learn_id}", summary="移除课程的学习课程关联")
async def remove_learn_from_lesson(
    lesson_id: str = Path(..., description="课程ID或LessonID"),
    learn_id: int = Path(..., description="学习课程ID")
):
    """
    移除课程与学习课程的关联关系
    支持整数ID（如：1）或LessonID字符串（如：Lesson-20251010-v1）
    """
    try:
        # 尝试判断是整数ID还是LessonID字符串
        if lesson_id.isdigit():
            # 整数ID
            lesson = Lesson.get_by_id(int(lesson_id))
        else:
            # LessonID字符串
            lesson = Lesson.get_by_lesson_id(lesson_id)
        
        if not lesson:
            raise HTTPException(status_code=404, detail="课程不存在")
        
        success = lesson.remove_from_learn(learn_id)
        if success:
            return {"message": "学习课程关联移除成功"}
        else:
            return {"message": "学习课程关联不存在或移除失败"}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"移除学习课程关联失败: {str(e)}")

@router.get("/{lesson_id}/learns", response_model=List[dict], summary="获取课程的关联学习课程")
async def get_lesson_learns(lesson_id: str = Path(..., description="课程ID或LessonID")):
    """
    获取课程关联的所有学习课程
    支持整数ID（如：1）或LessonID字符串（如：Lesson-20251010-v1）
    """
    try:
        # 尝试判断是整数ID还是LessonID字符串
        if lesson_id.isdigit():
            # 整数ID
            lesson = Lesson.get_by_id(int(lesson_id))
        else:
            # LessonID字符串
            lesson = Lesson.get_by_lesson_id(lesson_id)
        
        if not lesson:
            raise HTTPException(status_code=404, detail="课程不存在")
        
        learns = lesson.get_learns()
        return learns
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取关联学习课程失败: {str(e)}")

@router.get("/stats/count", summary="获取课程统计信息")
async def get_lesson_stats():
    """
    获取课程统计信息
    """
    try:
        total_count = Lesson.get_count()
        return {
            "total_lessons": total_count,
            "message": "统计信息获取成功"
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取统计信息失败: {str(e)}")

@router.get("/factories/list", response_model=List[str], summary="获取所有工厂列表")
async def get_factory_list():
    """
    获取所有可用的工厂列表
    """
    try:
        # 从数据库中动态获取所有工厂
        from app.db.database import db
        query = "SELECT DISTINCT factory FROM lesson ORDER BY factory"
        results = db.execute_query(query)
        factories = [row['factory'] for row in results if row['factory']]
        return factories if factories else []
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取工厂列表失败: {str(e)}")
